/**
 * @file trade_engine.cpp
 * @brief 交易引擎的实现
 * 
 * @details 该文件实现了交易引擎（TradeEngine）类的方法，
 * 包括构造函数、析构函数、主循环函数以及各种事件处理方法。
 * 交易引擎是交易系统的核心组件，负责协调市场数据处理、订单管理、
 * 风险控制和交易策略执行。
 * 
 * @author 原作者
 * @date 2023
 */

#include "trade_engine.h"

namespace Trading {
  /**
   * @brief 交易引擎的构造函数实现
   * 
   * @details 初始化交易引擎，设置客户端标识符、算法类型和相关组件。
   * 构造过程包括以下步骤：
   * 1. 初始化成员变量，包括客户端标识符、队列指针、日志记录器等
   * 2. 初始化交易组件，如特征引擎、仓位管理器、订单管理器和风险管理器
   * 3. 创建并初始化每个交易工具的订单簿对象
   * 4. 初始化函数包装器，设置默认的回调函数
   * 5. 根据算法类型创建相应的交易算法实例（做市商或流动性接受者）
   * 6. 记录初始化日志
   * 
   * @param client_id 客户端标识符，用于标识交易引擎实例
   * @param algo_type 算法类型，指定使用做市商或流动性接受者算法
   * @param ticker_cfg 交易工具配置映射，包含每个交易工具的配置信息
   * @param client_requests 客户端请求队列指针，用于发送订单请求
   * @param client_responses 客户端响应队列指针，用于接收订单响应
   * @param market_updates 市场数据更新队列指针，用于接收市场数据更新
   */
  TradeEngine::TradeEngine(Common::ClientId client_id,
                           AlgoType algo_type,
                           const TradeEngineCfgHashMap &ticker_cfg,
                           Exchange::ClientRequestLFQueue *client_requests,
                           Exchange::ClientResponseLFQueue *client_responses,
                           Exchange::MEMarketUpdateLFQueue *market_updates)
      : client_id_(client_id), outgoing_ogw_requests_(client_requests), incoming_ogw_responses_(client_responses),
        incoming_md_updates_(market_updates), logger_("trading_engine_" + std::to_string(client_id) + ".log"),
        feature_engine_(&logger_),
        position_keeper_(&logger_),
        order_manager_(&logger_, this, risk_manager_),
        risk_manager_(&logger_, &position_keeper_, ticker_cfg) {
    for (size_t i = 0; i < ticker_order_book_.size(); ++i) {
      ticker_order_book_[i] = new MarketOrderBook(i, &logger_);
      ticker_order_book_[i]->setTradeEngine(this);
    }

    // Initialize the function wrappers for the callbacks for order book changes, trade events and client responses.
    algoOnOrderBookUpdate_ = [this](auto ticker_id, auto price, auto side, auto book) {
      defaultAlgoOnOrderBookUpdate(ticker_id, price, side, book);
    };
    algoOnTradeUpdate_ = [this](auto market_update, auto book) { defaultAlgoOnTradeUpdate(market_update, book); };
    algoOnOrderUpdate_ = [this](auto client_response) { defaultAlgoOnOrderUpdate(client_response); };

    // Create the trading algorithm instance based on the AlgoType provided.
    // The constructor will override the callbacks above for order book changes, trade events and client responses.
    if (algo_type == AlgoType::MAKER) {
      mm_algo_ = new MarketMaker(&logger_, this, &feature_engine_, &order_manager_, ticker_cfg);
    } else if (algo_type == AlgoType::TAKER) {
      taker_algo_ = new LiquidityTaker(&logger_, this, &feature_engine_, &order_manager_, ticker_cfg);
    }

    for (TickerId i = 0; i < ticker_cfg.size(); ++i) {
      logger_.log("%:% %() % Initialized % Ticker:% %.\n", __FILE__, __LINE__, __FUNCTION__,
                  Common::getCurrentTimeStr(&time_str_),
                  algoTypeToString(algo_type), i,
                  ticker_cfg.at(i).toString());
    }
  }

  /**
   * @brief 交易引擎的析构函数实现
   * 
   * @details 清理交易引擎分配的资源，包括停止交易线程、
   * 释放交易算法实例和订单簿对象，并重置指针。
   * 析构过程包括以下步骤：
   * 1. 将运行标志设置为假，停止主循环
   * 2. 等待一秒，确保线程安全终止
   * 3. 释放交易算法实例（做市商或流动性接受者）
   * 4. 释放所有订单簿对象
   * 5. 重置队列指针
   */
  TradeEngine::~TradeEngine() {
    run_ = false;

    using namespace std::literals::chrono_literals;
    std::this_thread::sleep_for(1s);

    delete mm_algo_; mm_algo_ = nullptr;
    delete taker_algo_; taker_algo_ = nullptr;

    for (auto &order_book: ticker_order_book_) {
      delete order_book;
      order_book = nullptr;
    }

    outgoing_ogw_requests_ = nullptr;
    incoming_ogw_responses_ = nullptr;
    incoming_md_updates_ = nullptr;
  }

  /**
   * @brief 将客户端请求写入无锁队列的实现
   * 
   * @details 将交易请求（如下单、撤单等）写入无锁队列，由订单服务器消费并发送给交易所。
   * 具体步骤如下：
   * 1. 记录发送请求的日志
   * 2. 获取队列中下一个可写入的位置
   * 3. 将请求移动到该位置
   * 4. 更新队列的写入索引
   * 5. 测量写入操作的时间
   * 
   * @param client_request 要发送的客户端请求指针
   * @return void
   */
  auto TradeEngine::sendClientRequest(const Exchange::MEClientRequest *client_request) noexcept -> void {
    logger_.log("%:% %() % Sending %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                client_request->toString().c_str());
    auto next_write = outgoing_ogw_requests_->getNextToWriteTo();
    *next_write = std::move(*client_request);
    outgoing_ogw_requests_->updateWriteIndex();
    TTT_MEASURE(T10_TradeEngine_LFQueue_write, logger_);
  }

  /**
   * @brief 交易引擎的主循环函数实现
   * 
   * @details 交易引擎线程的主循环，不断处理来自交易所的订单响应和市场数据更新。
   * 循环过程如下：
   * 1. 首先检查并处理所有入站的客户端订单响应：
   *    - 获取下一个可读取的响应
   *    - 测量读取时间
   *    - 记录日志
   *    - 调用onOrderUpdate处理响应
   *    - 更新队列的读取索引
   *    - 更新最后事件时间
   * 2. 然后检查并处理所有入站的市场数据更新：
   *    - 获取下一个可读取的更新
   *    - 测量读取时间
   *    - 记录日志
   *    - 验证证券标识符有效
   *    - 将更新分发给相应的订单簿对象处理
   *    - 更新队列的读取索引
   *    - 更新最后事件时间
   * 3. 当run_标志为假时，循环结束
   * 
   * @return void
   */
  auto TradeEngine::run() noexcept -> void {
    logger_.log("%:% %() %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_));
    while (run_) {
      for (auto client_response = incoming_ogw_responses_->getNextToRead(); client_response; client_response = incoming_ogw_responses_->getNextToRead()) {
        TTT_MEASURE(T9t_TradeEngine_LFQueue_read, logger_);

        logger_.log("%:% %() % Processing %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                    client_response->toString().c_str());
        onOrderUpdate(client_response);
        incoming_ogw_responses_->updateReadIndex();
        last_event_time_ = Common::getCurrentNanos();
      }

      for (auto market_update = incoming_md_updates_->getNextToRead(); market_update; market_update = incoming_md_updates_->getNextToRead()) {
        TTT_MEASURE(T9_TradeEngine_LFQueue_read, logger_);

        logger_.log("%:% %() % Processing %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                    market_update->toString().c_str());
        ASSERT(market_update->ticker_id_ < ticker_order_book_.size(),
               "Unknown ticker-id on update:" + market_update->toString());
        ticker_order_book_[market_update->ticker_id_]->onMarketUpdate(market_update);
        incoming_md_updates_->updateReadIndex();
        last_event_time_ = Common::getCurrentNanos();
      }
    }
  }

  /**
   * @brief 处理订单簿变化的实现
   * 
   * @details 处理订单簿的变化，更新仓位管理器和特征引擎，并通知交易算法关于该更新。
   * 处理流程如下：
   * 1. 记录订单簿变化的日志，包括证券标识符、价格和侧向
   * 2. 获取当前的最优价格（BBO）
   * 3. 更新仓位管理器的BBO信息，并测量该操作的时间
   * 4. 更新特征引擎的订单簿信息，并测量该操作的时间
   * 5. 调用交易算法的订单簿更新回调函数，并测量该操作的时间
   * 
   * @param ticker_id 证券标识符
   * @param price 变化的价格
   * @param side 变化的侧向（买入或卖出）
   * @param book 变化的订单簿指针
   * @return void
   */
  auto TradeEngine::onOrderBookUpdate(TickerId ticker_id, Price price, Side side, MarketOrderBook *book) noexcept -> void {
    logger_.log("%:% %() % ticker:% price:% side:%\n", __FILE__, __LINE__, __FUNCTION__,
                Common::getCurrentTimeStr(&time_str_), ticker_id, Common::priceToString(price).c_str(),
                Common::sideToString(side).c_str());

    auto bbo = book->getBBO();

    START_MEASURE(Trading_PositionKeeper_updateBBO);
    position_keeper_.updateBBO(ticker_id, bbo);
    END_MEASURE(Trading_PositionKeeper_updateBBO, logger_);

    START_MEASURE(Trading_FeatureEngine_onOrderBookUpdate);
    feature_engine_.onOrderBookUpdate(ticker_id, price, side, book);
    END_MEASURE(Trading_FeatureEngine_onOrderBookUpdate, logger_);

    START_MEASURE(Trading_TradeEngine_algoOnOrderBookUpdate_);
    algoOnOrderBookUpdate_(ticker_id, price, side, book);
    END_MEASURE(Trading_TradeEngine_algoOnOrderBookUpdate_, logger_);
  }

  /**
   * @brief 处理成交事件的实现
   * 
   * @details 处理市场上的成交事件，更新特征引擎并通知交易算法关于该成交事件。
   * 处理流程如下：
   * 1. 记录成交事件的日志，包括市场数据更新的完整信息
   * 2. 更新特征引擎的成交信息，并测量该操作的时间
   * 3. 调用交易算法的成交事件回调函数，并测量该操作的时间
   * 
   * 成交信息对于交易算法做出决策非常重要，特别是对于需要跟踪市场流动性的算法。
   * 
   * @param market_update 市场数据更新指针，包含成交信息
   * @param book 相关的订单簿指针
   * @return void
   */
  auto TradeEngine::onTradeUpdate(const Exchange::MEMarketUpdate *market_update, MarketOrderBook *book) noexcept -> void {
    logger_.log("%:% %() % %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                market_update->toString().c_str());

    START_MEASURE(Trading_FeatureEngine_onTradeUpdate);
    feature_engine_.onTradeUpdate(market_update, book);
    END_MEASURE(Trading_FeatureEngine_onTradeUpdate, logger_);

    START_MEASURE(Trading_TradeEngine_algoOnTradeUpdate_);
    algoOnTradeUpdate_(market_update, book);
    END_MEASURE(Trading_TradeEngine_algoOnTradeUpdate_, logger_);
  }

  /**
   * @brief 处理订单更新的实现
   * 
   * @details 处理客户端订单响应，更新仓位管理器并通知交易算法关于该响应。
   * 处理流程如下：
   * 1. 记录订单响应的日志，包括客户端响应的完整信息
   * 2. 如果响应类型是成交（FILLED），则更新仓位管理器的成交信息，并测量该操作的时间
   * 3. 调用交易算法的订单更新回调函数，并测量该操作的时间
   * 
   * 订单响应包含了订单的状态变化信息，如新建、成交、取消等。
   * 对于成交类型的响应，需要更新仓位管理器的成交信息，以跟踪仓位和盈亏。
   * 
   * @param client_response 客户端订单响应指针
   * @return void
   */
  auto TradeEngine::onOrderUpdate(const Exchange::MEClientResponse *client_response) noexcept -> void {
    logger_.log("%:% %() % %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                client_response->toString().c_str());

    if (UNLIKELY(client_response->type_ == Exchange::ClientResponseType::FILLED)) {
      START_MEASURE(Trading_PositionKeeper_addFill);
      position_keeper_.addFill(client_response);
      END_MEASURE(Trading_PositionKeeper_addFill, logger_);
    }

    START_MEASURE(Trading_TradeEngine_algoOnOrderUpdate_);
    algoOnOrderUpdate_(client_response);
    END_MEASURE(Trading_TradeEngine_algoOnOrderUpdate_, logger_);
  }
}
